package epibot.WebRobots;

import epibot.EstruturasBiologicas.Epitopo;
import epibot.EstruturasBiologicas.Proteina;
import epibot.robot.Proxy.GereciadorDoProxy;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/*
 * http://www.syfpeithi.de/Scripts/MHCServer.dll/EpitopePrediction.htm
 *
 * Query to the SYFPEITHI algorithm
 */
public class SYFPEITHI {


    public static Proteina processCalibragem(String seq, String allele, String epi_len,
            String codProteina, String nomeSite) throws IOException {
        String rline; // Represents a line of the result table
        int row_count = 1;

        Proteina p = new Proteina(codProteina, nomeSite, allele, epi_len, 0); // só para armazenar a proteina e os epítopos

        String a = allele;
        if (allele.equals("HLA-A0201")
                || allele.equals("HLA-A1101")
                || allele.equals("HLA-B2705")
                || allele.equals("HLA-B3801")
                || allele.equals("HLA-B3901")
                || allele.equals("HLA-B3902")
                || allele.equals("HLA-B5101")
                || allele.equals("HLA-A2402")
                || allele.equals("HLA-A6801")
                || allele.equals("HLA-B0702")
                || allele.equals("HLA-B1402")
                || allele.equals("HLA-B1501")
                || allele.equals("HLA-B1510")
                || allele.equals("HLA-B2709")
                || allele.equals("HLA-B4001")
                || allele.equals("HLA-B4101")
                || allele.equals("HLA-B4402")
                || allele.equals("HLA-B4501")
                || allele.equals("HLA-B4701")
                || allele.equals("HLA-B4901")
                || allele.equals("HLA-B5001")) { //HLA-A*2402
            a = allele.replace("HLA-A", "HLA-A*");
            a = a.replace("HLA-B", "HLA-B*");
            String j1 = a.substring(6, 8);
            String j2 = a.substring(8, 10);
            a = a.replace(j1 + "" + j2, j1 + ":" + j2);

            //HLA-A*02:01
            //HLA-B*07:02
        }

        // build the URL
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        FormUtility form = new FormUtility(bos, null);
        try {
            form.add("Motif", a);
            form.add("amers", epi_len);
            form.add("SEQU", seq);
            form.add("DoIT", "++Run++");
            form.complete();
        } catch (IOException ex) {
            System.out.println("no FORM");
        }

        // Make the query
        String surl = "http://www.syfpeithi.de/bin/MHCServer.dll/EpitopePrediction?" + bos.toString();
        URL url = null;
        try {
            url = new URL(surl);
        } catch (MalformedURLException ex) {
            Logger.getLogger(SYFPEITHI.class.getName()).log(Level.SEVERE, null, ex);
        }

        // read the results an parse the table
        //InputStream is = url.openStream();
        InputStream is = null;
        Proxy proxy = GereciadorDoProxy.getConexao();
        try {
            if (proxy == null) {

                //System.out.println("sem proxy");
                is = url.openStream();

            } else {
                // System.out.println("com proxy");
                is = url.openConnection(proxy).getInputStream();
            }
        } catch (IOException ex) {
            System.out.println("open conexão");
            Logger.getLogger(SYFPEITHI.class.getName()).log(Level.SEVERE, null, ex);
        }

        ParseHTML parse = new ParseHTML(is);
        StringBuilder buffer = new StringBuilder();
        List<String> list = new ArrayList<String>();
        boolean capture = false;
        try {
            // select the result table
            if (!advance(parse, "table", 3)) {
                return null;
            }
        } catch (IOException ex) {
            System.out.println("no advance");
            Logger.getLogger(SYFPEITHI.class.getName()).log(Level.SEVERE, null, ex);
        }

        int rank = 0;
        String scoreAnt = "";

        // Parse the table. Ignores the head lines.
        int ch;
        int i, j;
        row_count = 0;   // Count the row that is being parsed
        HTMLTag tag;
        int numEp = 0, limite = 50;

        while ((ch = parse.read()) != -1) {
            if (ch == 0) {
                tag = parse.getTag();
                if (tag.getName().equalsIgnoreCase("tr")) {
                    list.clear();
                    capture = false;
                    buffer.setLength(0);
                } else if (tag.getName().equalsIgnoreCase("/tr")) {
                    /*
                     * Write each found epitop to the result file
                     */
                    if (list.size() > 0) {
                        /**
                         * Discard the 2 initial rows because they are the
                         * header
                         */
                        if (row_count > 2) {

                            String epitopo = list.get(1).replaceAll("\\W", "");
                            String posicao = list.get(0);
                            String score = list.get(2);

                            if (!score.equals(scoreAnt)) {
                                rank++;
                            }
                            scoreAnt = score;

                            if (numEp == limite) {
                                break;
                            }
                            numEp++;

                            p.addEpitopo(new Epitopo(epitopo, Integer.parseInt(posicao), Double.parseDouble(score), rank, p));

                        }
                        list.clear();
                    }
                    row_count++;
                } // Begin of a table cell
                else if (tag.getName().equalsIgnoreCase("td") && (row_count > 2)) {
                    buffer.setLength(0);
                    capture = true;
                } // End of a table cell
                else if (tag.getName().equalsIgnoreCase("/td") && (row_count > 2)) {
                    list.add(buffer.toString());
                    capture = false;
                } // End of table
                else if (tag.getName().equalsIgnoreCase("/table")) {
                    break;
                }
            } else {
                // Capture the content of the table cell
                if (capture) {
                    buffer.append((char) ch);
                }
            }
        }

        try {
            is.close();
        } catch (IOException ex) {
            System.out.println("close");
        }        
        return p;
    }// fim do metodo process

    /**
     * Avancça para a tag HTML especificado.
     *
     * @param parse o objeto de análise HTML para usar.
     * @param tag A tag HTML.
     * @param count quantas etiquetas como esta para encontrar.
     *
     * @return True se encontrou, false caso contrário.
     * @throws IOException Se ocorrer uma exceção durante a leitura.
     */
    private static boolean advance(ParseHTML parse, String tag, int count)
            throws IOException {
        int ch;
        while ((ch = parse.read()) != -1) {
            if (ch == 0) {
                if (parse.getTag().getName().equalsIgnoreCase(tag)) {
                    count--;
                    if (count <= 0) {
                        return true;
                    }
                }
            }
        }
        return false;
    }
}
